﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Widgetsphere.Autos.EFDAL;

namespace Widgetsphere.Autos.API
{
    public static class Utilities
    {
        /// <summary>
        /// This will remove the target file if it exists and move the soruce file to that name
        /// </summary>
        public static bool MoveFile(string source, string target)
        {
            var index = 0;
            do
            {
                try
                {
                    //Delete old file
                    if (File.Exists(target))
                    {
                        File.Delete(target);
                        System.Threading.Thread.Sleep(1000);
                    }
                    File.Move(source, target);
                    return true;
                }
                catch (Exception ex)
                {
                    index++;
                    if (index > 3)
                        throw;
                    else
                        System.Threading.Thread.Sleep(1000);
                }
            } while (true);
        }

        public static bool DeleteFileWithRetry(string fileName, int retryCount, bool throwError = true)
        {
            if (!File.Exists(fileName)) return false;
            if (retryCount < 0) retryCount = 0;

            var success = false;
            var tryCount = 0;
            do
            {
                try
                {
                    File.Delete(fileName);
                    success = true;
                }
                catch
                {
                    if (tryCount < retryCount) System.Threading.Thread.Sleep(1000);
                    tryCount++;
                }
            } while (!success && (tryCount <= retryCount));

            if (throwError && !success)
                throw new Exception("File '" + fileName + "' could not be deleted");

            return success;
        }

        public static string CallingIPAddress
        {
            get
            {
                try
                {
                    return GetCallingIPAddress(System.Web.HttpContext.Current.Request);
                }
                catch (Exception ex)
                {
                    return null;
                }
            }
        }

        public static string GetCallingIPAddress(System.Web.HttpRequest request)
        {
            try
            {
                var retval = request.UserHostAddress;
                if (string.IsNullOrEmpty(retval))
                    retval = request.ServerVariables["REMOTE_ADDR"];
                if (string.IsNullOrEmpty(retval)) retval = null;
                return retval;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        /// <summary>
        /// Remove HTML from string with Regex.
        /// </summary>
        public static string StripHtmlTags(string source)
        {
            return System.Text.RegularExpressions.Regex.Replace(source, "<.*?>", string.Empty);
        }

        /// <summary>
        /// This will remove all but a small set of HTML tags
        /// </summary>
        public static string CleanseHtml(this string text)
        {
            if (text == null) return string.Empty;
            try
            {
                //Allowed tags: UL,OL,LI,B,STRONG

                //Replace line breaks
                text = text.Replace("<br>", "\r\n", StringComparison.InvariantCultureIgnoreCase);
                text = text.Replace("<br >", "\r\n", StringComparison.InvariantCultureIgnoreCase);
                text = text.Replace("<br/>", "\r\n", StringComparison.InvariantCultureIgnoreCase);
                text = text.Replace("<br />", "\r\n", StringComparison.InvariantCultureIgnoreCase);

                //build replacement list
                var replacements = new Dictionary<string, string>();
                replacements.Add("<b>", "19aud8736fy463524cpe6d");
                replacements.Add("</b>", "19auds76d342jhd4cpe6d");

                replacements.Add("<ul>", "19azz0d8815sd24cpe6d");
                replacements.Add("</ul>", "19ckifuyf62jd3524cpe6d");

                replacements.Add("<ol>", "19mmzocud927dgh4cpe6d");
                replacements.Add("</ol>", "1900a7sjhjw7266dtu44cpe6d");

                replacements.Add("<li>", "19auccjduejji6812kde6d");
                replacements.Add("</li>", "19aud8c8jv73hd73j56pe6d");

                replacements.Add("<strong>", "19auccsdsd2ddfff3jji6812kde6d");
                replacements.Add("</strong>", "19chsyd7726fffj56pe6d");

                //Kill all <p> tags and replace </p> with line break
                text = text.Replace("<p>", string.Empty, StringComparison.InvariantCultureIgnoreCase);
                text = text.Replace("</p>", "\r\n", StringComparison.InvariantCultureIgnoreCase);

                //Perform replacements
                foreach (var key in replacements.Keys)
                {
                    text = text.Replace(key, replacements[key], StringComparison.InvariantCultureIgnoreCase);
                }

                //Now look and see if there are any unmatched tags. If so remove the whole lot
                text = FixUnmatchedTag(text, replacements["<b>"], replacements["</b>"]);
                text = FixUnmatchedTag(text, replacements["<ul>"], replacements["</ul>"]);
                text = FixUnmatchedTag(text, replacements["<ol>"], replacements["</ol>"]);
                text = FixUnmatchedTag(text, replacements["<li>"], replacements["</li>"]);
                text = FixUnmatchedTag(text, replacements["<strong>"], replacements["</strong>"]);

                //Strip HTML
                text = StripHtmlTags(text);

                //Now replace the allowed tags
                foreach (var key in replacements.Keys)
                {
                    text = text.Replace(replacements[key], key, StringComparison.InvariantCultureIgnoreCase);
                }

                //Change <b> to <strong>
                text = text.Replace("<b>", "<strong>", StringComparison.InvariantCultureIgnoreCase);
                text = text.Replace("</b>", "</strong>", StringComparison.InvariantCultureIgnoreCase);

                return text;
            }
            catch (Exception ex)
            {
                Logger.LogError(ex);
                throw;
            }
        }

        /// <summary>
        /// If token1 and token2 do not have same number of occurrances then remove both from string
        /// </summary>
        private static string FixUnmatchedTag(string text, string token1, string token2)
        {
            var c1 = System.Text.RegularExpressions.Regex.Matches(text, token1).Count;
            var c2 = System.Text.RegularExpressions.Regex.Matches(text, token2).Count;
            if (c1 != c2)
            {
                text = text.Replace(token1, string.Empty);
                text = text.Replace(token2, string.Empty);
            }
            return text;
        }

        /// <summary>
        /// Converts LR and CR to HTML breaks
        /// </summary>
        public static string ConvertLineBreaksToHTML(this string s)
        {
            if (s == null) s = string.Empty;
            s = s.Replace("\r\n", "\n");
            s = s.Replace("\r", "\n");
            s = s.Replace("\n", "<br />");
            return s;
        }

        /// <summary>
        /// Converts HTML breaks to spaces
        /// </summary>
        public static string HTMLRemoveLineBreaks(this string s)
        {
            if (s == null) s = string.Empty;
            s = s.Replace("<br />", " ");
            return s;
        }

        public static bool IsCrawler(System.Web.HttpRequest request)
        {
            return false;
            //try
            //{
            //    if (request == null) return false;
            //    if (string.IsNullOrEmpty(request.UserAgent)) return false;
            //    // set next line to "bool isCrawler = false; to use this to deny certain bots
            //    bool isCrawler = request.Browser.Crawler;
            //    // Microsoft doesn't properly detect several crawlers
            //    if (!isCrawler)
            //    {
            //        // put any additional known crawlers in the Regex below
            //        // you can also use this list to deny certain bots instead, if desired:
            //        // just set bool isCrawler = false; for first line in method 
            //        // and only have the ones you want to deny in the following Regex list
            //        var regEx = new System.Text.RegularExpressions.Regex("Slurp|slurp|ask|Ask|Teoma|teoma|Googlebot|googlebot|bingbot|msnbot|webcrawler|exabot|Exabot|gigabot|Gigabot|baiduspider|Baiduspider|scribdbot|SiteUptime.com|YandexBot|MJ12bot|NextGenSearchBot|AhrefsBot|NextGenSearchBot|AdsBot");
            //        isCrawler = regEx.Match(request.UserAgent).Success;
            //    }

            //    //If not found ten look at the logged IP addres
            //    if (!isCrawler)
            //    {
            //        using (var context = new AutosEntities())
            //        {
            //            var ip = GetCallingIPAddress(request);
            //            isCrawler = context.CrawlerIP.Any(x => x.IPAddress == ip);
            //        }
            //    }

            //    return isCrawler;

            //}
            //catch (Exception ex)
            //{
            //    Logger.LogError(ex);
            //    return false;
            //}
        }

        public static string Replace(this string originalString, string oldValue, string newValue, StringComparison comparisonType)
        {
            try
            {
                int startIndex = 0;
                while (true)
                {
                    startIndex = originalString.IndexOf(oldValue, startIndex, comparisonType);
                    if (startIndex == -1)
                        break;

                    originalString = originalString.Substring(0, startIndex) + newValue + originalString.Substring(startIndex + oldValue.Length);

                    startIndex += newValue.Length;
                }

                return originalString;

            }
            catch (Exception ex)
            {
                throw;
            }
        }

        public static bool IsMobileBrowser(string agent)
        {
            try
            {
                if (string.IsNullOrEmpty(agent)) return false;
                if (agent.Length < 4) return false;
                var u = agent;
                var b = new Regex(@"(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                var v = new Regex(@"1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                if ((b.IsMatch(u) || v.IsMatch(u.Substring(0, 4))))
                {
                    return true;
                }
                return false;
            }
            catch (Exception ex)
            {
                //Logger.LogInfo("IP: " + SessionHelper.IpAddress + " / Agent: " + agent);
                Logger.LogWarning(ex.ToString());
                return false;
            }
        }

        public static DateTime MaxDate(DateTime a, DateTime b)
        {
            return a > b ? a : b;
        }

        public static DateTime? MaxDate(DateTime? a, DateTime? b)
        {
            if (a == null && b == null) return null;
            if (a != null && b == null) return a;
            if (a == null && b != null) return b;
            return MaxDate(a.Value, b.Value);
        }

        private static Random _rnd = new Random();
        public static string RandomString(int length)
        {
            if (length < 1) length = 1;
            var sb = new StringBuilder();
            for (var ii = 0; ii < length; ii++)
            {
                sb.Append((char)_rnd.Next(65, 91));
            }
            return sb.ToString();
        }

        public static bool IsValidUrl(string url)
        {
            Uri myUri;
            return Uri.TryCreate(url, UriKind.Absolute, out myUri);
        }

        public static string SerializeSoap<T>(T value)
        {
            if (value == null)
            {
                return null;
            }

            var serializer = new System.Xml.Serialization.XmlSerializer(typeof(T));
            var settings = new System.Xml.XmlWriterSettings();
            settings.Encoding = new UnicodeEncoding(false, false); // no BOM in a .NET string
            settings.Indent = false;
            settings.OmitXmlDeclaration = false;

            using (var textWriter = new StringWriter())
            {
                using (var xmlWriter = System.Xml.XmlWriter.Create(textWriter, settings))
                {
                    serializer.Serialize(xmlWriter, value);
                }
                return textWriter.ToString();
            }
        }

    }
}